package com.mobileares.midp.widgets.client.tab;

import com.google.gwt.animation.client.Animation;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: Tom
 * Date: 2011-7-14
 * Time: 9:33:59
 * To change this template use File | Settings | File Templates.
 */
public class FrameTabPanel extends Composite implements HasSelectionHandlers<Object> {

    protected VerticalPanel vp;
    private HorizontalPanel tabBar;
    protected HorizontalPanel container;
    private SimplePanel preview;
    private SimplePanel next;
    protected FrameTabItem selected;

    private int left = 0;
    private static final int _BT_WIDTH = 13;
    private static final int _DEFAULT_ITEM_WIDTH = 100;
    private NextAnimation nextA = new NextAnimation();
    private PreviewAnimation previewA = new PreviewAnimation();
    private FlowPanel flowPanel;
    private Map<FrameTabItem, SimplePanel> myItems = new HashMap<FrameTabItem, SimplePanel>();

    public FrameTabPanel() {
        vp = new VerticalPanel();
        vp.setWidth("100%");
        createBar();

        vp.add(tabBar);
        vp.setCellHeight(tabBar, "29px");
        initMain();
        initWidget(vp);
    }


    protected void initMain() {
        flowPanel = new FlowPanel();
        flowPanel.setWidth("100%");
//        flowPanel.setHeight("100%");
        vp.add(flowPanel);
    }

    @Override
    public void setWidth(String width) {
        vp.setWidth(width);
    }


    private void createBar() {
        tabBar = new HorizontalPanel();
        tabBar.setStyleName("fish-tab-bar");
        tabBar.setWidth("100%");

        container = new HorizontalPanel();
        container.setStyleName("fish-tab");
        container.setWidth("100px");

        initPreviewButton();
        initNextButton();
        tabBar.add(preview);
        tabBar.setCellWidth(preview, _BT_WIDTH + "px");
        tabBar.add(next);
        tabBar.setCellWidth(next, _BT_WIDTH + "px");
        SimplePanel wrapper = new SimplePanel();
        wrapper.setWidth("100%");
        wrapper.setStyleName("fish-tab-wrapper");
        wrapper.add(container);
        tabBar.add(wrapper);


    }


    private void initPreviewButton() {
        preview = new SimplePanel() {
            public void onBrowserEvent(Event event) {
                switch (DOM.eventGetType(event)) {
                    case Event.ONCLICK:
                        previewA.run(500);
                        break;
                    case Event.ONMOUSEOVER:
                        addStyleDependentName("enable");
                        break;
                    case Event.ONMOUSEOUT:
                        removeStyleDependentName("enable");
                        break;
                }
            }
        };
        preview.sinkEvents(Event.ONCLICK);
        preview.sinkEvents(Event.MOUSEEVENTS);
        preview.setStyleName("fish-tab-preview");
        preview.setVisible(false);
    }

    private void initNextButton() {
        next = new SimplePanel() {
            public void onBrowserEvent(Event event) {
                switch (DOM.eventGetType(event)) {
                    case Event.ONCLICK:
                        nextA.run(500);
                        break;
                    case Event.ONMOUSEOVER:
                        addStyleDependentName("enable");
                        break;
                    case Event.ONMOUSEOUT:
                        removeStyleDependentName("enable");
                        break;
                }
            }
        };
        next.sinkEvents(Event.ONCLICK);
        next.sinkEvents(Event.MOUSEEVENTS);
        next.setVisible(false);
        next.setStyleName("fish-tab-next");
    }

    public void addItem(String text, String width, Widget widget) {
        addItem(text, text, width, widget);
    }

    public void addItem(String text, Object userObject, String width, Widget widget) {
        FrameTabItem item = new FrameTabItem(this, widget);
        item.setUserObject(userObject);
        item.setText(text);
        addItem(item, width);
    }

    public void addItem(String text, Widget widget) {
        addItem(text, _DEFAULT_ITEM_WIDTH + "px", widget);
    }

    public void addItem(FrameTabItem item, String width) {

        container.add(item);
        container.setCellWidth(item, width);
        SimplePanel wrapper = new SimplePanel();
        wrapper.setWidget(item.getShowWidget());
        wrapper.setVisible(false);
        flowPanel.add(wrapper);
        myItems.put(item, wrapper);

    }


    void setSelectItem(FrameTabItem selected) {
        if (this.selected != null)
            myItems.get(this.selected).setVisible(false);
        myItems.get(selected).setVisible(true);
        myItems.get(selected).setWidget(selected.getShowWidget());
        if (this.selected != null)
            this.selected.removeSelectedStyle();
        this.selected = selected;
        this.selected.addSelectedStyle();
        if (selected.getEvent() != null)
            selected.getEvent().onSelect();
        SelectionEvent.fire(FrameTabPanel.this, selected.getUserObject());

    }

    public void setSelectItem(Object userObject) {
        FrameTabItem item = getItem(userObject);
        if (item != null)
            setSelectItem(item);
    }

    public FrameTabItem getSelectItem() {
        return selected;
    }

    void closeTabItem(FrameTabItem item) {

        myItems.get(item).removeFromParent();
        container.remove(item);
        myItems.remove(item);
        calculateBarWidth();
        if (selected == item) selected = null;
        if (container.getWidgetCount() >= 1)
            setSelectItem((FrameTabItem) container.getWidget(container.getWidgetCount() - 1));

    }

    public List<FrameTabItem> getItems() {
        List r = new ArrayList();
        for (FrameTabItem item : myItems.keySet()) {
            r.add(item);
        }
        return r;
    }

    public FrameTabItem getItem(Object userObject) {
        for (FrameTabItem item : myItems.keySet()) {
            if (item.getUserObject().equals(userObject)) {
                return item;
            }
        }
        return null;
    }

    protected void calculateBarWidth() {
//        System.out.println("(tabBar.getOffsetWidth() - _BT_WIDTH * 2)"+(tabBar.getOffsetWidth() - _BT_WIDTH * 2));
//        System.out.println("(container.getOffsetWidth()"+container.getOffsetWidth());
        if ((tabBar.getOffsetWidth() - _BT_WIDTH * 2) < container.getOffsetWidth()) {
            preview.setVisible(true);
            next.setVisible(true);
        } else {
            preview.setVisible(false);
            next.setVisible(false);
            setTabBarPosition(0);
        }

    }

    @Override
    protected void onLoad() {
        calculateBarWidth();
    }

//    @Override
//    public void onBrowserEvent(Event event) {
//
//        switch (DOM.eventGetType(event)) {
//            case Event.ONCLICK:
//
//                break;
//        }
//        super.onBrowserEvent(event);
//    }

    /**
     * Adds a {@link com.google.gwt.event.logical.shared.SelectionEvent} handler.
     *
     * @param objectSelectionHandler the handler
     * @return the registration for the event
     */
    public HandlerRegistration addSelectionHandler(SelectionHandler<Object> objectSelectionHandler) {
        return addHandler(objectSelectionHandler, SelectionEvent.getType());
    }

    private class NextAnimation extends Animation {
        private int interval = 50;

        @Override
        protected void onUpdate(double progress) {
            int current = (int) (interval * progress);
            if (FrameTabPanel.this.left + current > 0)
                FrameTabPanel.this.left = 0;
            else
                FrameTabPanel.this.left += current;
            setTabBarPosition(FrameTabPanel.this.left);


        }
    }

    private class PreviewAnimation extends Animation {
        private int interval = -50;

        @Override
        protected void onUpdate(double progress) {
            int current = (int) (interval * progress);

            int minWidth = tabBar.getOffsetWidth() - _BT_WIDTH * 2;
            if (FrameTabPanel.this.left + current + container.getOffsetWidth() < minWidth) {
                FrameTabPanel.this.left = minWidth - container.getOffsetWidth();
            } else
                FrameTabPanel.this.left += current;

            setTabBarPosition(FrameTabPanel.this.left);


        }
    }


    private void setTabBarPosition(int left) {
        DOM.setStyleAttribute(container.getElement(), "left", left + "px");
    }

}